import {isExtensionStartPage} from '@/lib/utils';
import {saveFaviconToCache, cleanupExpiredFaviconCache} from "@/lib/faviconCache.ts";

// 背景脚本（MV3 Service Worker）：处理标签页管理和跨标签页通信

// 增强日志记录工具
const log = {
    info: (message: string, ...args: any[]) => console.log(`[Tab Lite Background] ${message}`, ...args),
    error: (message: string, ...args: any[]) => console.error(`[Tab Lite Background] ${message}`, ...args),
    warn: (message: string, ...args: any[]) => console.warn(`[Tab Lite Background] ${message}`, ...args),
    debug: (message: string, ...args: any[]) => console.debug(`[Tab Lite Background] ${message}`, ...args)
};

chrome.runtime.onInstalled.addListener(() => {
    log.debug("Service Worker 已安装并启动");

    // 检查chrome.alarms API是否可用（开发环境可能不可用）
    if (typeof chrome !== 'undefined' && chrome.alarms) {
        try {
            // 创建favicon缓存清理定时任务
            chrome.alarms.create('cleanupFaviconCache', {
                periodInMinutes: 360 // 每6小时执行一次清理
            });
            log.debug("Favicon缓存定时清理任务已创建（每6小时执行一次）");
        } catch (error) {
            log.warn("创建定时任务失败，可能在开发环境中:", error);
        }
    } else {
        log.warn("chrome.alarms API不可用，跳过定时任务创建（开发环境正常）");
    }
});

// 检查API可用性后再监听定时任务
if (typeof chrome !== 'undefined' && chrome.alarms && chrome.alarms.onAlarm) {
    chrome.alarms.onAlarm.addListener(async (alarm: chrome.alarms.Alarm) => {
        if (alarm.name === 'cleanupFaviconCache') {
            log.debug('开始执行favicon缓存清理...');
            try {
                await cleanupExpiredFaviconCache();
                log.debug('Favicon缓存清理完成');
            } catch (error) {
                log.error('Favicon缓存清理失败:', error);
            }
        }
    });
} else {
    log.warn("chrome.alarms API不可用，跳过定时任务监听器注册（开发环境正常）");
}

/**
 * 消息监听器：处理来自页面的标签页管理请求
 * 注意：必须在顶层注册，不能使用async函数作为监听器
 */
chrome.runtime.onMessage.addListener((
    message: any,
    sender: chrome.runtime.MessageSender,
    sendResponse: (response?: any) => void
): boolean | void => {
    log.debug('收到消息:', message.type, message.data);

    // 使用包装器模式处理异步操作
    if (message.type === 'SAVE_COLLECTION_AND_MANAGE_TABS') {
        handleAsyncMessage(async () => {
            return await handleSaveCollectionAndManageTabs(message.data, sender);
        }, sendResponse);

        // 返回true表示会异步发送响应，保持消息通道开放
        return true;
    }

    if (message.type === 'CREATE_NEW_TAB_SMART') {
        handleAsyncMessage(async () => {
            return await createNewTabSmart();
        }, sendResponse);

        return true;
    }

    if (message.type === 'FETCH_FAVICON') {
        handleAsyncMessage(async () => {
            return await handleFetchFavicon(message.data);
        }, sendResponse);

        return true;
    }

    log.debug('未处理的消息类型:', message.type);
    // 未处理的消息类型，不返回任何值
});

/**
 * 异步消息处理包装器 - 2024年最佳实践模式
 * 避免直接使用async函数作为消息监听器
 */
function handleAsyncMessage(asyncFn: () => Promise<any>, sendResponse: (response?: any) => void) {
    Promise.resolve(asyncFn())
        .then(result => sendResponse({success: true, result}))
        .catch(error => {
            log.error('异步操作失败:', error);
            sendResponse({success: false, error: error.message});
        });
}

/**
 * 在Background Script中处理保存集合后的标签页管理
 * 这是核心逻辑，完全在Background中执行，避免页面关闭导致的中断
 */
async function handleSaveCollectionAndManageTabs(
    data: { nonPinnedTabIds: number[]; pinnedTabsCount: number },
    _sender: chrome.runtime.MessageSender
): Promise<{ message: string }> {
    const {nonPinnedTabIds, pinnedTabsCount} = data;

    try {
        // 记录原窗口ID（更可靠：从待关闭标签中获取），避免依赖 sender.tab
        // 可能为 undefined（例如传入空列表）
        const sourceWindowId = await getWindowIdFromAnyTab(nonPinnedTabIds);

        // 若关闭后可能导致“没有任何窗口”，则先创建一个承载页，避免 SW 被回收导致后续失败
        // 条件：当前窗口无固定标签且系统仅有一个普通窗口（或无法判定原窗口）
        if (pinnedTabsCount === 0) {
            const wins = await chrome.windows.getAll({windowTypes: ['normal'], populate: false});
            const onlyOneNormal = wins.length <= 1;
            const isSingleSource = onlyOneNormal && (!wins[0]?.id || !sourceWindowId || wins[0]?.id === sourceWindowId);
            if (isSingleSource) {
                await chrome.tabs.create({windowId: sourceWindowId, active: true});
            }
        }

        // 1) 关闭非固定标签页
        if (nonPinnedTabIds.length > 0) {
            await chrome.tabs.remove(nonPinnedTabIds);
        }

        // 2) 创建/激活起始页（尽量在原窗口；若窗口已被关闭则智能选择可用窗口或创建新窗口）
        await focusStartPageSmart({preferredWindowId: sourceWindowId, expectWindowAlive: pinnedTabsCount > 0});

        const result = {message: `成功处理标签页管理: 关闭${nonPinnedTabIds.length}个标签页，固定标签页${pinnedTabsCount}个`};
        return result;

    } catch (error) {
        log.error('标签页管理失败:', error);
        throw new Error(`标签页管理失败: ${error instanceof Error ? error.message : String(error)}`);
    }
}

/**
 * 智能创建新标签页：独立的功能，可被其他地方调用
 */
async function createNewTabSmart(): Promise<{ message: string }> {
    try {
        const action = await focusStartPageSmart();
        if (action === 'activated-existing') return {message: '已激活存在的新标签页'};
        if (action === 'created-in-window') return {message: '已在现有窗口创建新标签页'};
        if (action === 'created-new-window') return {message: '已创建新窗口'};
        return {message: '已完成'};
    } catch (error) {
        log.error('智能新标签页创建失败:', error);
        throw new Error(`新标签页创建失败: ${error instanceof Error ? error.message : String(error)}`);
    }
}

// ---------------- 统一的“起始页聚焦/创建”实现 ----------------

type FocusAction = 'activated-existing' | 'created-in-window' | 'created-new-window' | 'noop';

async function focusStartPageSmart(params?: {
    preferredWindowId?: number | undefined;
    expectWindowAlive?: boolean; // 若为true，将优先使用首选窗口，否则可能已被关闭
    candidateWindows?: chrome.windows.Window[]; // 供调用者传入，避免重复查询
}): Promise<FocusAction> {
    const windows = params?.candidateWindows ?? await chrome.windows.getAll({windowTypes: ['normal'], populate: false});

    // 1) 若有“应仍存活”的首选窗口，优先在该窗口复用/创建
    if (params?.preferredWindowId && params?.expectWindowAlive) {
        try {
            const w = await chrome.windows.get(params.preferredWindowId);
            if (w && w.id) {
                await chrome.windows.update(w.id, {focused: true});
                const tabs = await chrome.tabs.query({windowId: w.id});
                log.debug('检查窗口标签页:', {windowId: w.id, tabsCount: tabs.length, tabs: tabs});
                for (let i = tabs.length - 1; i >= 0; i--) {
                    const t = tabs[i];
                    if (isExtensionStartPage(t)) {
                        if (t.id) await chrome.tabs.update(t.id, {active: true});
                        return 'activated-existing';
                    }
                }
                await chrome.tabs.create({windowId: w.id, active: true});
                return 'created-in-window';
            }
        } catch {
            // 可能窗口已关闭，继续降级
        }
    }

    // 2) 当前窗口可能已关闭：先在“聚焦窗口”中寻找最后一个起始页
    const focused = windows.find(w => w.focused);
    if (focused?.id) {
        const tabs = await chrome.tabs.query({windowId: focused.id});
        log.debug('检查窗口标签页:', {windowId: focused.id, tabsCount: tabs.length, tabs: tabs});
        for (let i = tabs.length - 1; i >= 0; i--) {
            const t = tabs[i];
            if (isExtensionStartPage(t)) {
                await chrome.windows.update(focused.id, {focused: true});
                if (t.id) await chrome.tabs.update(t.id, {active: true});
                return 'activated-existing';
            }
        }
    }

    // 3) 任意窗口中寻找最后一个起始页（按窗口顺序；每个窗口从后向前）
    for (const w of windows) {
        if (!w.id) continue;
        const tabs = await chrome.tabs.query({windowId: w.id});
        log.debug('检查窗口标签页:', {windowId: w.id, tabsCount: tabs.length, tabs: tabs});
        for (let i = tabs.length - 1; i >= 0; i--) {
            const t = tabs[i];
            if (isExtensionStartPage(t)) {
                await chrome.windows.update(w.id, {focused: true});
                if (t.id) await chrome.tabs.update(t.id, {active: true});
                return 'activated-existing';
            }
        }
    }

    // 4) 未找到：若有任何窗口，选择聚焦窗口或第一个窗口创建起始页；否则创建新窗口
    const target = focused ?? windows[0];
    if (target?.id) {
        await chrome.windows.update(target.id, {focused: true});
        await chrome.tabs.create({windowId: target.id, active: true});
        return 'created-in-window';
    }

    await chrome.windows.create({type: 'normal', focused: true});
    return 'created-new-window';
}

async function getWindowIdFromAnyTab(tabIds: number[]): Promise<number | undefined> {
    if (!tabIds || tabIds.length === 0) return undefined;
    for (const id of tabIds) {
        try {
            const t = await chrome.tabs.get(id);
            if (t.windowId) return t.windowId;
        } catch {
            // 某些标签可能已不可用，尝试下一个
        }
    }
    return undefined;
}

/**
 * 处理favicon抓取请求 - 在service worker中执行，避免CORS限制
 */
async function handleFetchFavicon(data: { url: string; savedFavicon?: string }): Promise<{
    dataUrl: string;
    source: string
}> {
    const {url, savedFavicon} = data;

    // 提取域名用于缓存键
    const domain = getDomainFromUrl(url);

    try {
        // 构造候选源列表（优先级顺序）
        const candidates: Array<{ url: string; source: string }> = [];

        // 若保存时拿到了 tab.favIconUrl，优先使用
        if (savedFavicon && /^https?:/i.test(savedFavicon)) {
            candidates.push({url: savedFavicon, source: 'saved'});
        }

        // 国内可访问的公共源
        candidates.push({
            url: `https://icon.horse/icon/${encodeURIComponent(domain)}`,
            source: 'icon.horse'
        });

        // 谷歌favicon服务作为备选
        candidates.push({
            url: `https://www.google.com/s2/favicons?sz=256&domain_url=${encodeURIComponent(url)}`,
            source: 'google'
        });

        // 依次尝试各个候选源
        for (const {url: candidateUrl, source} of candidates) {
            try {
                // 通过fetch直接获取图像数据（service worker不受CORS限制）
                const response = await fetch(candidateUrl, {
                    method: 'GET',
                    credentials: 'omit',
                    cache: 'no-store',
                    mode: 'cors'
                });

                if (!response.ok) {
                    throw new Error(`HTTP ${response.status}`);
                }

                // 读取为Blob以保留原始MIME类型
                const blob = await response.blob();
                const arrayBuffer = await blob.arrayBuffer();

                // 验证是否为有效图像（检查文件头）
                if (!isValidImageBuffer(arrayBuffer)) {
                    throw new Error('无效图像格式');
                }

                // 转换为dataURL返回给前端
                const dataUrl = await blobToDataURL(blob);

                // 异步保存到缓存（不阻塞响应）
                saveFaviconToBackgroundCache(url, arrayBuffer, blob.type, source).catch(error => {
                    log.error('保存favicon缓存失败:', error);
                });

                return {dataUrl, source};
            } catch (error) {
                log.debug('favicon抓取失败:', {
                    candidateUrl,
                    source,
                    error: error instanceof Error ? error.message : String(error)
                });
                // 继续尝试下一个候选源
            }
        }

        // 所有候选都失败，返回默认SVG
        log.warn('所有favicon源都失败，使用fallback');
        return {
            dataUrl: getDefaultFaviconSvgDataUrl(),
            source: 'fallback'
        };

    } catch (error) {
        log.error('favicon抓取过程异常:', error);
        return {
            dataUrl: getDefaultFaviconSvgDataUrl(),
            source: 'fallback'
        };
    }
}

// 从URL提取域名
function getDomainFromUrl(url: string): string {
    try {
        return new URL(url).hostname;
    } catch {
        return url;
    }
}

// 检查ArrayBuffer是否为有效图像（简单文件头验证）
function isValidImageBuffer(buffer: ArrayBuffer): boolean {
    const view = new Uint8Array(buffer);
    if (view.length < 4) return false;

    // PNG: 89 50 4E 47
    if (view[0] === 0x89 && view[1] === 0x50 && view[2] === 0x4E && view[3] === 0x47) return true;
    // JPEG: FF D8 FF
    if (view[0] === 0xFF && view[1] === 0xD8 && view[2] === 0xFF) return true;
    // GIF: 47 49 46 38
    if (view[0] === 0x47 && view[1] === 0x49 && view[2] === 0x46 && view[3] === 0x38) return true;
    // WebP: 52 49 46 46 (RIFF header)
    if (view[0] === 0x52 && view[1] === 0x49 && view[2] === 0x46 && view[3] === 0x46) return true;
    // ICO: 00 00 01 00
    if (view[0] === 0x00 && view[1] === 0x00 && view[2] === 0x01 && view[3] === 0x00) return true;
    // SVG通常以<或者BOM开头，简单检测
    if (view[0] === 0x3C || (view[0] === 0xEF && view[1] === 0xBB && view[2] === 0xBF)) return true;

    return false;
}

// 将Blob转换为DataURL
function blobToDataURL(blob: Blob): Promise<string> {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = () => resolve(reader.result as string);
        reader.onerror = () => reject(reader.error);
        reader.readAsDataURL(blob);
    });
}

// 获取默认SVG favicon的DataURL
function getDefaultFaviconSvgDataUrl(): string {
    const svg = `
<svg width="32" height="32" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<!--  <rect width="24" height="24" rx="3" fill="#6b7280"/>-->
  <path d="M13 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V9z"
        fill="none" stroke="#6b7280" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
  <polyline points="13 3 13 9 19 9"
        fill="none" stroke="#6b7280" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>`;

    // 使用URL编码方式（避免 btoa 的 Unicode/引号问题）
    const encodedSvg = encodeURIComponent(svg);
    return `data:image/svg+xml;charset=utf-8,${encodedSvg}`;
}

// 保存favicon到后台缓存（使用重构后的缓存系统）
async function saveFaviconToBackgroundCache(
    url: string,
    arrayBuffer: ArrayBuffer,
    mimeType: string,
    source: string
): Promise<void> {
    try {
        // 动态导入缓存模块以避免循环依赖
        await saveFaviconToCache(url, arrayBuffer, mimeType, source as any);
        log.debug('favicon缓存保存成功:', {url, mimeType, source, size: arrayBuffer.byteLength});
    } catch (error) {
        log.error('保存favicon缓存失败:', error);
    }
}
